package com.ccl.iot.publics;import java.util.ArrayList;

import android.graphics.RectF;
import android.view.MotionEvent;

public class TouchResolver {
	/*
	 * 	Motion information
	 */
	private class MotionInfo {
		public float iX;
		public float iY;
		
		MotionInfo(float aX, float aY){
			iX = aX;
			iY = aY;
		}
	}
	
	/*
	 * 	Non-static functions
	 */
	private float iStep = 0;
	private ArrayList<MotionInfo> iDownInfo = null;
	private RectF iDownRect = null;
	private RectF iRect = null;
	
	TouchResolver(float aStep){
		iStep = aStep;
	}
	
	public RectF getDownRect(){
		return iDownRect;
	}
	
	public void onTouchDown(float aX, float aY){
		
	}
	
	public void onTouchMove(float aSrcX, float aSrcY, float aDstX, float aDstY){
		
	}
	
	public void onSelectRectChange(RectF aSrc, RectF aDst){
		
	}
	
	public void onTouchCancel(){
		
	}
	
	private RectF getRect(ArrayList<MotionInfo> aMotions){
		if (aMotions != null){
			int tCount = aMotions.size();
			
			if (tCount > 1){
				RectF tRect = new RectF();
				MotionInfo tMotion1 = aMotions.get(0);
				MotionInfo tMotion2 = aMotions.get(1);
				
				if (tMotion1.iX < tMotion2.iX){
					if (tMotion1.iY < tMotion2.iY){
						tRect.set(tMotion1.iX, tMotion1.iY, tMotion2.iX, tMotion2.iY);
					}else{
						tRect.set(tMotion1.iX, tMotion2.iY, tMotion2.iX, tMotion1.iY);
					}
				}else{
					if (tMotion1.iY > tMotion2.iY){
						tRect.set(tMotion2.iX,  tMotion2.iY, tMotion1.iX, tMotion1.iY);
					}else{
						tRect.set(tMotion2.iX, tMotion1.iY, tMotion1.iX, tMotion2.iY);
					}
				}
				
				for (int i = 2; i < tCount; i++){
					tMotion1 = aMotions.get(i);
					
					tRect.union(tMotion1.iX, tMotion1.iY);
				}
				
				return tRect;
			}
		}
		
		return null;
	}
	
	public boolean onTouchEvent(MotionEvent event) {
		if (event != null){
			//Debugger.Debug(event);
			
			switch (event.getAction() & MotionEvent.ACTION_MASK){
				case MotionEvent.ACTION_DOWN:{
					if (iDownInfo == null){
						iDownInfo = new ArrayList<MotionInfo>();
					}
					
					if (iDownInfo.size() == 0){
						iDownInfo.add(new MotionInfo(event.getX(), event.getY()));
					}
					
					onTouchDown(event.getX(), event.getY());
					
					return true;
				}
				case MotionEvent.ACTION_POINTER_DOWN:{
					if (iDownInfo != null){
						for (int i = iDownInfo.size(), tCount = event.getPointerCount(); i < tCount; i++){
							iDownInfo.add(new MotionInfo(event.getX(i), event.getY(i)));
						}
						
						iRect = getRect(iDownInfo);
						iDownRect = iRect;
					}
					
					return true;
				}
				case MotionEvent.ACTION_POINTER_UP:{
					if (iDownInfo != null){
						int tIndex = event.getActionIndex();
						
						if (tIndex < iDownInfo.size()){
							iDownInfo.remove(tIndex);
							
							iRect = getRect(iDownInfo);
							iDownRect = iRect;
							
							if (iRect == null){
								onSelectRectChange(iRect, null);
							}
						}
					}
					
					return true;
				}
				case MotionEvent.ACTION_UP:{
					if (iDownInfo != null && iDownInfo.size() > 0){
						iDownInfo.clear();
					}
					
					onTouchCancel();
					
					return true;
				}
				case MotionEvent.ACTION_MOVE:{
					if (iDownInfo != null){
						int tSize = iDownInfo.size();
						int tCount = event.getPointerCount();
						
						if (tSize == tCount && tCount > 0){
							if (tCount == 1){
								float tX = event.getX();
								float tY = event.getY();
								
								MotionInfo tInfo = iDownInfo.get(0);
								
								if (Math.abs(tX - tInfo.iX) > iStep || Math.abs(tY - tInfo.iY) > iStep){
									onTouchMove(tInfo.iX, tInfo.iY, tX, tY);
									
									tInfo.iX = tX;
									tInfo.iY = tY;
								}
							}else if (iRect != null){
								ArrayList<MotionInfo> tMotions = new ArrayList<MotionInfo>();
								RectF tRect;
								
								for (int i = 0; i < tCount; i++){
									tMotions.add(new MotionInfo(event.getX(i), event.getY(i)));
								}
								
								tRect = getRect(tMotions);
								
								if (Math.abs(tRect.left - iRect.left) > iStep ||
										Math.abs(tRect.right - iRect.right) > iStep ||
										Math.abs(tRect.top - iRect.top) > iStep ||
										Math.abs(tRect.bottom - iRect.bottom) > iStep ||
										Math.abs(tRect.width() - iRect.height()) > iStep ||
										Math.abs(tRect.height() - iRect.height()) > iStep){
									onSelectRectChange(iRect, tRect);
									
									iDownInfo = tMotions;
									iRect = tRect;
								}
							}
						}
						
						return true;
					}
				}
			}
		}
		
		return false;
	}
}
